﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;

namespace VeryGoodSync
{
    /// <summary>
    /// 全局配置
    /// </summary>
    public class VeryGood
    {
        /// <summary>
        /// 该配置定义的Job清单
        /// </summary>
        public VeryGoodJob[] Jobs { get; set; }

        /// <summary>
        /// 加载配置
        /// </summary>
        /// <returns></returns>
        public static VeryGood LoadConfig()
        {
            if (!File.Exists("VeryGoodSync.xml")) return null;
            Log.WriteMessage($"正在重新加载配置文件...");
            try
            {
                var xml = new XmlDocument();
                xml.Load("VeryGoodSync.xml");
                var jobs = xml.SelectNodes("VeryGood/Job");
                if (jobs == null) throw new Exception("无法读取Job内容");
                var jobList = new List<VeryGoodJob>();
                var index = 0;
                foreach (XmlNode job in jobs)
                {
                    var item = new VeryGoodJob { Name = $"Job-{index++}" };
                    if (job.Attributes != null)
                    {
                        if (int.TryParse(job.Attributes["delay"].Value, out var delay)) item.Delay = delay;
                        item.Name = job.Attributes["name"].Value;
                    }

                    var disabled = job.Attributes?["disabled"]?.Value;
                    if (string.Equals(disabled, "true", StringComparison.OrdinalIgnoreCase))
                    {
                        Log.WriteMessage($"{item.Name}已经停用");
                        continue;
                    }

                    item.Source = job.SelectSingleNode("Source")?.InnerText;
                    if (string.IsNullOrWhiteSpace(item.Source)) throw new Exception($"Job：{item.Name}没有配置监视目录");
                    var plugins = new List<VeryGoodJobPlugin>();
                    foreach (XmlNode childNode in job.ChildNodes)
                    {
                        if (childNode.Name != "Plugin") continue;
                        var typeStr = childNode.Attributes?["type"].Value;
                        if (string.IsNullOrWhiteSpace(typeStr)) throw new Exception($"Job：{item.Name}的插件配置有误");
                        var plugin = new VeryGoodJobPlugin { Type = Type.GetType(typeStr) };
                        if (plugin.Type == null) throw new Exception($"无法找到类型为[{typeStr}]的同步插件");
                        plugin.Arguments = new Dictionary<string, string>();
                        foreach (XmlNode argNode in childNode.ChildNodes)
                        {
                            plugin.Arguments[argNode.Name] = argNode.InnerText;
                        }

                        plugins.Add(plugin);
                    }

                    item.Plugins = plugins.ToArray();
                    Log.WriteMessage($"已经成功载入任务[{item.Name}]");
                    jobList.Add(item);
                }

                Log.WriteMessage($"任务载入完毕，合计{jobList.Count}个");

                return new VeryGood()
                {
                    Jobs = jobList.ToArray()
                };
            }
            catch (Exception ex)
            {
                Ui.ShowError(ex);
                return null;
            }
        }
    }

    /// <summary>
    /// 单个Job的描述
    /// </summary>
    public class VeryGoodJob
    {
        /// <summary>
        /// 该Job对应要同步的源
        /// </summary>
        public string Source { get; set; }

        /// <summary>
        /// 名称
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 监测到变更后的延时，单位秒，默认为0，不延时
        /// </summary>
        public int Delay { get; set; }

        /// <summary>
        /// 该Job的同步插件
        /// </summary>
        public VeryGoodJobPlugin[] Plugins { get; set; }

    }

    /// <summary>
    /// 工作插件配置
    /// </summary>
    public class VeryGoodJobPlugin
    {
        /// <summary>
        /// 插件参数集合
        /// </summary>
        public Dictionary<string, string> Arguments { get; set; }

        /// <summary>
        /// 插件类型
        /// </summary>
        public Type Type { get; set; }
    }
}
